#include <iostream>
#include <map>
#include "../TestFramework/TestAutoPtr.h"
#include "../TestFramework/NonCopyable.h"
#include "../TestFramework/TestString.h"
#include "../TestFramework/TestVector.h"
#include "Console.h"
#include "Item.h"
#include "ItemConsumer.h"
#include "ItemProvider.h"

namespace Explorer
{
    class RootItem : public Item
    {
    public:
        virtual ItemName GetName() const
        {
            return ItemName(L"Root");
        }

        virtual ItemType GetType() const
        {
            return ItemType("root");
        }

        virtual bool IsParentType() const
        {
            return true;
        }
    };

    class RegistryRoot : public Item
    {
    public:
        virtual ItemName GetName() const
        {
            return ItemName(L"Registry");
        }

        virtual ItemType GetType() const
        {
            return ItemType("registry");
        }

        virtual bool IsParentType() const
        {
            return true;
        }
    };

    class RegistryProvider : public ItemProvider
    {
    public:
        virtual void ReportChildren(const Item& item, ItemConsumer& items) const
        {
        }

        virtual void ReportRoot(ItemConsumer& items) const
        {
            items.Consume(Root);
        }

        virtual bool IsTypeSupported(const ItemType& type) const
        {
            return true; //todo
        }

        virtual bool IsParentType(const Item& item) const
        {
            return true; //todo
        }

    private:
        RegistryRoot Root;
    };

    class RootProvider : public ItemProvider
    {
    public:
        typedef TestFramework::TestVector<const ItemProvider*> ItemProviders;

        virtual void ReportChildren(const Item& item, ItemConsumer& items) const
        {
            ItemProviders::ConstIterator iter = Providers.Begin();
            for (; iter != Providers.End(); ++iter)
            {
                (*iter)->ReportRoot(items);
            }
        }

        virtual void ReportRoot(ItemConsumer&/* items*/) const
        {
        }

        virtual bool IsParentType(const Item& item) const
        {
            return item.IsParentType();
        }

        virtual bool IsTypeSupported(const ItemType& type) const
        {
            return true;//todo
        }

        void AddProvider(const ItemProvider& provider)
        {
            Providers.PushBack(&provider);
        }

    private:
        ItemProviders Providers;
    };
}

int main(int/* argc*/, char* /*argv[]*/)
{
    TestFramework::TestString input;
    Explorer::RootProvider provider;
    Explorer::RegistryProvider registry;
    provider.AddProvider(registry);
    Explorer::RootItem item;
    Explorer::Console console(provider, item);
    do
    {
        std::cout << "> ";
        input.Clear();
        std::cin >> input;
        console.ProcessInput(input);
    }
    while (input != "exit");

    return 0;
}
